//var sprintf = require('sprintf').sprintf;
var owsessions=require('./sessions');
var rewriter=require('./rewriter').rewriter;
var model_factory=require('./model_factory').ModelFactory;
var GenericModel=require('./generic_model').GenericModel;
var model_builder=require('./model_builder').ModelBuilder;
//require('fs');
var Directory=require('fs').Directory;
var File=require('fs').File;
require('http');

function safe(t) {
	if (t==undefined) return "--undefined--";
	if (t==null) return "--null--";
	if (typeof t=="string") return t.replace(/\&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
	return t;
}

/*****************************************************************************/
String.prototype.repeat=function(num)
{
	return new Array(num+1).join(this);
}

/*****************************************************************************/
function OneWorldCmsServer()
{
	this.iterations=0;
	this.paths_rules={
		html: "html/",
		sql: "code/sql/",
		views: "code/views/",
		cache: "cache/",
		models: "code/models/",
		i18n: "i18n/",
		controllers: "code/controllers/",
		models_config: "database/models.js"
	};
	return this;
}

/*****************************************************************************/
function send_error_notification(space,dump)
{
	if (!space.site) return;
	if (!space.site.error_notify) return;
	var en=space.site.error_notify;
	if (en.prototype!=Array) en=[en];
	var subject=space.site.code+", OWCMS threw error";
	var fields="";
	function escape1(a) {
		if (typeof obj!="string") return a;
		return a.replace(/\n/g,"\\n",/\t/g,"\\t");
	}
	for (var k in space.fields) {
		fields+=k;fields+="=";
		if (space.fields[k].length>1000) fields+=escape1(space.fields[k].substr(0,1000)); else fields+=escape1(space.fields[k]);
		fields+="\n";
	}
	var from="no-reply@"+(space.site.names?space.site.names[0]:space.site.domains[0]);
	var body="URL: "+space.action+"\n"+
			"IP: "+system.env.REMOTE_ADDR+"\n"+
			"User-agent: "+system.env.HTTP_USER_AGENT+"\n"+
			"uid: "+space.uid+"\n\n"+
			"GET/POST fields:\n"+fields+"\n"+
			"ERROR DUMP:\n"+dump;
	en.forEach(function(to) {
		var headers = {
			From: from,
			"Content-Type": 'text/plain; charset="UTF-8"'
		};
		var auth;
		require("mail").mail(to, subject, body, headers, auth);
	});
}

/*****************************************************************************/
function Dumper(obj, indent,findent) {
	if (!indent) indent="";
	if (!findent) findent="";
	if (indent.length>4) return findent+"...\n";
	if (obj==null) return findent+"null\n";
	if (obj==undefined) return findent+"undefined\n";
	if (obj.toJSON) obj=obj.toJSON();
	switch (typeof obj) {
		case "string":
			return findent+'"'+obj.replace(/"/g,"\\\"")+'"\n';
		case "number":
		case "boolean":
			return findent+obj+'\n';
		case "object":
			if (obj.constructor==Array) {
				var ret=findent+" [\n";
				for (var i=0;i<obj.length;i++) {
					ret+=Dumper(obj[i],indent+"\t",indent+"\t");
				}
				ret+=indent+"]\n";
				return ret;
			} else if (obj.constructor.toString().match(/Error|Exception/)) {
				var ret=obj.toString();
				if (obj.stack) ret+="\nStack\n"+obj.stack+"\n";
				return ret;
			} else {
				ret=findent+"{";
				if (obj.constructor!=Object) ret+=" /*"+obj.constructor+"*/";;
				ret+="\n";
				var arr=[];
				for (var item in obj) arr.push(item);
				arr.sort();
				arr.forEach(function(item) {
					if (item.charAt(0)=='_') return;
					ret+=indent+"\t"+item+": "+Dumper(obj[item],indent+"\t","");
				});
				ret+=indent+"}\n";
				return ret;
			}
			break;
		default:
			return findent+(typeof obj)+'\n';
	}
}

/*****************************************************************************/
function dateTimeFormatted()
{
	var date=new Date();
	return sprintf.sprintf("%04d-%02d-%02d %02d:%02d:%02d",date.getFullYear(),date.getMonth()+1,date.getDay(),date.getHours(),date.getMinutes(),date.getSeconds());
}

/*****************************************************************************/
OneWorldCmsServer.prototype.init=function() {
	var options=this.options=require('../../config/server.js').config;
	for (var k in options.system.paths) {
		if (options.system.paths[k].match(/^\//)) continue;
		if (k=="uploads_subfolder") continue;
		options.system.paths[k]=system.getcwd()+"/"+options.system.paths[k];
	}
	var dir=new Directory("config/sites-enabled");
	dir.listFiles().forEach(function(x) {
		if (!x.match(/\.js$/)) return;
		options.sites.push(require('../../config/sites-enabled/'+x).site);
	});
	options.system.locales={};
	this.localeLoad(options.system.language,options.system.paths.i18n,options.system.locales);
	this.localeLoad(options.system.locales_load,options.system.paths.i18n,options.system.locales);
//	for (var j=0;k<options.system.locales_load.length;j++) {
//		var ln=options.system.locales_load[j];
//		options.system.locales[ln]=require(options.system.paths.i18n+ln+'.js').i18n;
//	}
	options.system.refs={
		controllers: {},
		models: {},
		functions: {},
		models_add: {}
	};
	this.views=require('./views').create();
	this.sql_module=require('./sql');
	this.siteByName={};
	this.siteByDomain={};
	this.loadModule(options.system.refs,require('./viewcompiler'),['functions','controllers']);
	this.loadModules(options.system);
	for (var j=0;j<options.sites.length;j++) {
		var site=options.sites[j];
		site.system=options.system;
		for (var i=0;i<site.names.length;i++) this.siteByName[site.names[i]]=site;
		if (site.domains) for (var i=0;i<site.domains.length;i++) this.siteByDomain[site.domains[i]]=site;
		this.setSitePaths(site);
		site.locales={};
		this.localeLoad(site.language,site.paths.i18n,site.locales,site);
		this.localeLoad(site.language,options.system.paths.i18n,options.system.locales);
		this.localeLoad(site.locales_load,site.paths.i18n,site.locales,site);
		this.localeLoad(site.locales_load,options.system.paths.i18n,options.system.locales);
		site.viewsconfig={
			views:[this.options.system.paths.views],
			cache:[this.options.system.paths.cache]
		};
		if (site.preload) {
			for (var k=0;k<site.preload.length;k++) {
				this.loadModules(site,options.system,site.preload[k]);
				if (site.preload[k].paths.views) {
					site.viewsconfig.views.unshift(site.preload[k].paths.views);
					site.viewsconfig.cache.unshift(site.preload[k].paths.cache);
				}
			}
		}
		site.viewsconfig.views.unshift(site.paths.views);
		site.viewsconfig.cache.unshift(site.paths.cache);
		this.loadModules(site,options.system);
		if (site.use_as_default_site) this.defaultSite=site;
	}
}

/*****************************************************************************/
OneWorldCmsServer.prototype.setSitePaths=function(site) {
	for (var k in this.paths_rules) {
		if (!site.paths[k]) site.paths[k]=site.paths.basepath+this.paths_rules[k];
	}
}

/*****************************************************************************/
OneWorldCmsServer.prototype.localeLoad=function(lang,path,hash,isSite) {
	if (!lang) return;
	if (lang.constructor==Array) {
		for (var j=0;j<lang.length;j++) this.localeLoad(lang[j],path,hash);
		return;
	}
	if (hash[lang]) return;
	var f=new File(path+lang+".js");
//	if (isSite) throw "Site "+path+lang+".js, exists="+f.exists()+"\n"+Dumper(isSite);
	if (!f.exists()) return;
	hash[lang]=require(path+lang+".js").i18n;
}

/*****************************************************************************/
OneWorldCmsServer.prototype.loadModules=function(site,fallback,source) {
	var types1=['controllers','models'];
	var types2=['controllers','models','functions'];
	if (!site.refs) {
		site.refs={controllers: {},models: {},functions: {},models_add:{}};
		if (fallback) {
			for (var i=0;i<types2.length;i++) {
				var fbhash=fallback.refs[types2[i]];
				var dhash=site.refs[types2[i]];
				for (var k in fbhash) dhash[k]=fbhash[k];
			}
		}
	}
	if (!source) source=site;
	for (var j=0;j<types1.length;j++) {
		var type1=types1[j];
		if (!site[type1]) continue;
		var carr=source[type1];
		var cpath=source.paths[type1];
		for (var i=0;i<carr.length;i++) {
			if (site.throw_require_errors) {
				this.loadModule(site.refs,require(cpath+carr[i]),types2,carr[i],site.code);
			} else {
				try {
					this.loadModule(site.refs,require(cpath+carr[i]),types2,carr[i],site.code);
				} catch(e) {
					if (!site.require_errors) site.require_errors="";
					site.require_errors+="FILE: "+cpath+carr[i]+"\n";
					site.require_errors+=Dumper(e);
					site.require_errors+="\n\n\n";
				}
			}
		}
	}
}

/*****************************************************************************/
OneWorldCmsServer.prototype.loadModule=function(refs,r,types2,module_name,site_name) {
	types2.forEach(function(type2) {
		var rt2=r[type2];
		if (!rt2) return;
		if (type2=="models") {
			if (typeof rt2 == "function") {
				rt2=rt2(GenericModel);
				for (var mname in rt2) {
					refs[type2][mname]=rt2[mname];
					if (!refs[type2+"_add"][mname]) refs[type2+"_add"][mname]={};
					for (var mmname in refs[type2+"_add"][mname]) refs[type2][mname].prototype[mmname]=refs[type2+"_add"][mname][mmname];
				}
			} else {
				for (var mname in rt2) {
					for (var mmname in rt2[mname]) {
						if (refs[type2][mname]) refs[type2][mname].prototype[mmname]=rt2[mname][mmname];
						if (!refs[type2+"_add"][mname]) refs[type2+"_add"][mname]={};
//						if (!refs[type2+"_add"][mname]) throw (site_name?("Site "+site_name):"System")+", module "+module_name+", models_add['"+mname+"'] does not exists";
						refs[type2+"_add"][mname][mmname]=rt2[mname][mmname];
					}
//					if (site_name=="erp1.relsyst.ru" && mname=="user") throw Dumper({model:refs[type2][mname],model_add:refs[type2+"_add"][mname]});
				}
			}
		} else {
			for (var cname in rt2) refs[type2][cname]=rt2[cname];
		}
	});
	if (r.onload) r.onload(refs);
}

/*****************************************************************************/
OneWorldCmsServer.prototype.work=function(req,resp) {
//	try {
		if (system.env.TERM || system.args.length>1) {
			this.work_args(system.args);
//			throw(Dumper(system));
//			this.iterate(new ServerRequest("/",system.env),new ServerResponse(function(x) {system.stdout(x);} ));
		}
		else this.iterate(req,resp);
/*	} catch (e) {
		var ret="<html><body><h1>HTTP ERROR 500 GRAND</h1><pre>"+Dumper(e)+"</pre></body></html>";
		response.status(500);
		response.header({"Content-type": 'text/html; charset=utf-8'});
		response.write(ret);
		try {
			var f=new File(space.site.paths.cache+"last.html");
			f.open("w");
			f.write(ret);
			f.write("\n\n");
			f.write(Dumper(request.get));
			f.write(Dumper(request.post));
//			f.write(Dumper(request.files));
			f.close();
		} catch(e) {
		}
	}*/
}

/*****************************************************************************/
OneWorldCmsServer.prototype.work_args=function(args) {
	var h={};
	var i=1;
	while (i<args.length) {
		var arr;
		if (arr=args[i].match(/^--(.*)/)) {
			h[arr[1]]=args[i+1];
			i+=2;
		} else {
			throw new Error("Unknown argument "+args[i]);
		}
	}
	if (h.help) {
		switch (h.help) {
			case "gen-global-models":
				throw new Error("Usage:\n"+args[0]+" --mode gen-global-models\n\n");
			case "gen-models":
				throw new Error("Usage:\n"+args[0]+" --mode gen-models [--models-parsed-config ModelsParsedConfigFile.js]\n\n");
			case "parse-global-models":
				throw new Error("Usage:\n"+args[0]+" --mode parse-global-models --site SiteName\n\n");
			case "parse-models":
				throw new Error("Usage:\n"+args[0]+" --mode parse-models --site SiteName --models-source-config ModelsSourceConfigFile.js\n\n");
			case "url":
				throw new Error("Usage:\n"+args[0]+" --mode url --site SiteName [--cnt benchmark-requests-counts] --page /url/\n\n");
			case "exec-function":
				throw new Error("Usage:\n"+args[0]+" --mode exec-function --site SiteName --function FunctionName\n\n");
			case "import-files":
				throw new Error("Usage:\n"+args[0]+" --mode import-files --site SiteName --path /path/ --folder folderId --user loginOrId\n\n");
			default:
				throw new Error("Unknown mode "+h.help);
				
		}
	}
	if (!h.mode) throw new Error(
			"Usage:\n"+args[0]+" [options] --mode ModeName\n"+
			"Available modes: parse-models parse-global-models gen-models gen-global-models url exec-function import-files\n"+
			"Help about mode: "+args[0]+" --help ModeName\n\n"
	);
//	if (!h.site) throw("no --site SiteName option!\n\n");
	var space={
		server_name: h.site,
		controllers: this.options.system.refs.controllers,
		models: this.options.system.refs.models,
		functions: this.options.system.refs.functions,
		views: this.views,
		system: this.options.system,
		Dumper: Dumper,
		owsessions:owsessions,
		complain: send_error_notification
	};
	var site;
	if (space.server_name) {
		site=this.siteByName[space.server_name];
		if (!site && this.siteByDomain) {
			var domain=space.server_name.match(/^([\w\-]+)\.(.+)$/)[2];
			site=this.siteByDomain[domain];
			if (!site) throw new Error("No site "+space.server_name+" found\n");
		}
	}
	space.site=site;
	if (!space.site) {
		//throw("No site "+space.server_name+" found\n");
		this.deconfigure(space);
	} else {
		this.configure(space,site);
	}
	switch (h.mode) {
		case "parse-global-models":
			h.global=1;
		case "parse-models":
			var mb=new model_builder(space.site,space.system,space);
			mb.parse_models(h);
			break;
		case "gen-global-models":
			h.global=1;
		case "gen-models":
			var mb=new model_builder(space.site,space.system,space);
			mb.gen_models(h);
			break;
		case "url":
			var itercnt=h.cnt||1;
			var rcons=require("http").ServerResponse;
			for (var iter=0;iter<itercnt;iter++) {
				this.iterate({
					method: "GET",
					silent: h.cnt?1:0,
					get: {},
					files: {},
					uri: h.page,
					server_name: h["site"],
					cookie: {}
				},new rcons(system.stdout,function (a,b) {} ));//function(x) {system.stdout(x);} ));
			}
			break;
		case "exec-function":
			if (!space.functions[h["function"]]) {
				var r="";
				for (var k in space.functions) r+="\t"+k+"\n";
				throw new Error("No function "+h["function"]+" in space.functions, contents is:\n"+r);
			}
			space.functions[h["function"]](space,h);
			break;
		case "import-files":
			space.functions.import_files(space,h.path,h.user,h.folder);
			break;
		default:
			throw new Error("Unknown mode "+h.mode+"\n");
			break;
	}
	if (site) site.sql.commit();
}

/*****************************************************************************/
function site_option(space,x)
{
	var a=space.site;
	var b=space.system;
	x.forEach(function(i) {
		if (a) a=a[i];
		if (b) b=b[i];
	});
	return a?a:b;
}

/*****************************************************************************/
OneWorldCmsServer.prototype.iterate=function(req,res) {
	try {
		req.silent=0;
		var req_uri=system.env.REQUEST_URI || req.uri || "/";
		this.iterations++;
		var space={
			v8iteration: this.iterations,
			req: req,
			res: res,
			fields: req[req.method.toLowerCase()],
			page: {
				statusCode: 200,
				responseHeaders: {"Content-type": 'text/html; charset=utf-8'}
			},
			complain: send_error_notification,
			uid: 0,
			roles: {},
			role_ids: {},
			user: {},
			action: req_uri.match(/^([^?]*)/)[1],
			Dumper: Dumper,
			server_name: system.env.SERVER_NAME||req.server_name,
			controllers: this.options.system.refs.controllers,
			models: this.options.system.refs.models,
			functions: this.options.system.refs.functions,
			views: this.views,
			system: this.options.system,
			site_option: site_option,
			owsessions:owsessions
		};
		space.action_src=space.action;
		var site=this.siteByName[space.server_name];
		if (!space.fields) space.fields={};
		if (space.fields.set_mobile_preference) {
			var exp=new Date(new Date().getTime() + 1000*24*60*60*1000);
			space.res.cookie("mobile_preference",space.fields.set_mobile_preference,exp,'/',site.cookie_domain);
			space.req.cookie.mobile_preference=space.fields.set_mobile_preference;
		}
		if (space.action=="/") {
			var mp=space.req.cookie.mobile_preference;
			switch (mp) {
				case "mobile":
					space.action="/index-mobile/";
					break;
				case "desktop":
					space.action="/index/";
					break;
				default:	
					if (site && site.has_mobile && system.env.HTTP_USER_AGENT.match(/mobile|iPhone|SymbianOS|Opera mini|Opera mobi/i) && !system.env.HTTP_USER_AGENT.match(/ipad|gt-p5100|gt-n7000/i)) {
						space.action="/index-mobile/";
					} else {
						space.action="/index/";
					}
			}
		}
		if (!space.action.match(/\/$/)) space.action+="/";
		if (!site && this.siteByDomain) {
			var domain=space.server_name.match(/^([\w\-]+)\.(.+)$/)[2];
			site=this.siteByDomain[domain];
		}
		if (!site && this.defaultSite) site=this.defaultSite;
		space.site=site;
		var ret;
		ret=this.processPage(space,site);
		if (site.output_postprocess) ret=site.output_postprocess(space,ret);
	} catch (e) {
		space.page.statusCode=500;
		ret="<html><body><div style='border: 1px dotted gray; padding: 5px;'><h1>HTTP ERROR 500</h1><div><b>Trying to render page "+space.action+"</b></div><pre>"+safe(Dumper(e))+"</pre></div></body></html>";
		this.send_error_notification(space,Dumper(e));
		//this.render_http_error(space,500,Dumper(e));
	}
	if (space.page.no_output) {
		if (space.site) space.site.sql.commit();
		return;
	}
//	ret=Dumper(req);

	if (!req.silent) {
		res.status(space.page.statusCode);
		res.header(space.page.responseHeaders);
		res.write(ret);
		if (space.site) space.site.sql.commit();
	}
	if (space.site && space.site.paths.cache) {
		try {
			var f=new File(space.site.paths.cache+"last.html");
			f.open("w");
			f.write(ret);
			f.write("\n\n");
			for (var k in space) {
				if (typeof space[k] == "function") {f.write("space."+k+"=function ...\n");continue;}
				f.write("space."+k+"="+space[k]+"\n");
			}
			f.write("get="+Dumper(space.req.get));
			f.write("post="+Dumper(space.req.post));
			f.write("files="+Dumper(space.req.files));
			f.close();
		} catch(e) {
		}
	}
}

/*****************************************************************************/
OneWorldCmsServer.prototype.processPage=function(space,site) {
	if (!site) {
		this.deconfigure(space);
		return this.render_http_error(space,404,"no_site");
	}
	try {
		this.configure(space,site);
	} catch (e) {
//		throw('Error configuring site - '+e.message);
		this.deconfigure(space);
		return this.render_http_error(space,500,e);
	}
	site.sql.setHref(space);
	var auth_error=owsessions.auth(space,this.processPage2);
	site.rewriter.work(space);
	if (site.rewrite) site.rewrite(space);
	var action=space.action;

	var siteapp=this;
	var arr;

	// If data was already generated by rewrite controller
	if (action==undefined || space.no_content) {
		if ("body" in space) return space.body;
		return "";
	}

	if (arr=action.match(/^(\/.+)-preview(\d+)(\w*)\.(\w+)/)) {
		return siteapp.mkpreview(space,arr[1],arr[2],arr[3],arr[4]);

	} else if (arr=action.match(/^\/admin-(\w+)\/$/)) {
		return siteapp.processAdminPage(space,arr[1],0);
	
	} else if (arr=action.match(/^\/admin_popup-(\w+)\/$/)) {
		return siteapp.processAdminPage(space,arr[1],1);


	} else if (action=="/admin/") {
		return siteapp.processAdminPage(space,undefined);

	} else if (action=="/client-side-views/") {
		return siteapp.buildClientSideViews(space);

	} else if (action=="/ajaj-auth/") {
		space.fields.ajaj=1;
		if (!space.uid || auth_error) {
			if (space.fields.onerror_response) return space.fields.onerror_response;
			return siteapp.render_http_error(space,"login");
		}
		if (space.fields.onsuccess_response) return space.fields.onsuccess_response;
		return JSON.stringify({refresh: 1})+"\n\n";
	}
	var usel=site.use_language?site.use_language:site.language;
	var page=space.site.mfact.get("page",{alias:action});
//	var page=space.site.sql.execute_and_fetch_one("pages/get_by_alias",{alias:action});
	if (!page) return siteapp.render_http_error(space,404,action);
	if (!page.title) page.title=page.name;
	if (page.hide_anon==1 && space.uid==0) return siteapp.render_http_error(space,403);
	if (page.hide_reg==1 && space.uid) return siteapp.render_http_error(space,403);
	if (page.role_id && !(space.role_ids[page.role_id])) return siteapp.render_http_error(space,403);
	space.pageinfo=page;
	if (page.prerun) {
		try {
			if (typeof space.controllers[page.prerun]=="function") {
				if (page.prerun_param) {
					var evaltext="space.prerun_output=space.controllers[page.prerun](space,"+page.prerun_param+");";
					eval(evaltext);
				} else {
					space.prerun_output=space.controllers[page.prerun](space);
				}
			} else if (space.controllers[page.prerun]) {
				if (page.prerun_param) {
					var evaltext="space.prerun_output=space.controllers[page.prerun][space.fields.mode||'index'](space,"+page.prerun_param+");";
					eval(evaltext);
				} else {
					space.prerun_output=space.controllers[page.prerun][space.fields.mode||'index'](space);
				}
			} else {
				throw "No controller "+page.prerun;
			}
		} catch (e) {
			space.prerun_output="<div style='border: 1px dashed gray;padding: 4px; margin: 4px;'><h1>prerun has thrown an error</h1>";
			if (typeof e == "string") {
				space.prerun_output+="<pre>"+safe(e.toString())+"</pre></div>";
			} else {
				space.prerun_output+="<div><b>"+safe(e.toString())+"</b></div><pre>"+safe(space.Dumper(e))+"</pre></div>";
			}
			this.send_error_notification(space,Dumper(e));
		}
	}
	if (space.no_output) return "";
	if (space.fields.ajaj) {
		if (space.fields["is-iframe"]) {
			space.output=space.prerun_output;
			return space.views.process("system/ajajform_iframe",space);
		} else {
			return space.prerun_output||space.output;
		}
	}
	site.sql.execute_and_fetch("page_blocks/list",{page_id: page.id}).forEach(function(pblock) {
		var a=pblock.body;
		if (usel && "body_"+usel in pblock) a=pblock["body_"+usel];
		if (a=="<p></p>") a=null;
		var ptc=pblock.place_type_code;
		if (pblock && a && a.length && (ptc=="tmpltext" || ptc=="tmplhtml" || ptc=="tmplimage" || ptc=="tmplgdbe")) {
			var arr;
			if (arr=a.match(/^<p>\s*({{[^<>]+}})\s*<\/p>\s*$/)) a=arr[1];
			a=siteapp.views.apply(a,space);
		}
		space[pblock.place_code]=a;
	});
	return siteapp.views.process('pagetemplates/'+page.template_id,space);
//	return siteapp.show_debug_page(space);
}

/*****************************************************************************/
OneWorldCmsServer.prototype.buildClientSideViews=function(space)
{
	var folder=space.fields.folder;
	if (!folder.match(/^\w+$/)) return "";
	return this.views.clientSide(space,folder);
}

/*****************************************************************************/
OneWorldCmsServer.prototype.processAdminPage=function(space,name,is_popup)
{
	var style=space.req.cookie['admin-panel-theme']||"bw";

	space.is_popup=is_popup;
	if (space.fields['set-theme']) {
		style=space.fields['set-theme'];
		space.res.cookie("admin-panel-theme",style,new Date(2100,01,01,0,0,0,0),'/');
	}
	space.style=style;
	if (!space.uid) return this.views.process('pagetemplates/adminpanel/'+style+'/enter',space);
	if (!name) {
		space.body=this.views.process('widgets/adminpanel/body',space);
	} else {
		try {
			space.body=space.controllers['admin_'+name](space);
		} catch(e) {
			space.body="";
			if (!space.fields.ajaj) space.body+="<pre>";
			space.body+=e+"\n\n";
			if (typeof e=="object") {
				for (var i in e) {
					space.body+=i+":"+e[i]+"\n";
				}
			}
			if (!space.fields.ajaj) space.body+="</pre>";
		}
	}
	if (space.fields.ajaj) {
		if (space.fields["is-iframe"]) {
			space.output=space.body;
			return space.views.process("system/ajajform_iframe",space);
		} else {
			return space.body;
		}
	}
	return this.views.process('pagetemplates/adminpanel/'+style+'/'+(is_popup?'popup':'body'),space);
}

/*****************************************************************************/
OneWorldCmsServer.prototype.deconfigure=function(space) {
	this.views.setGlobalspace(space);
	this.views.setPaths([this.options.system.paths.views],[this.options.system.paths.cache]);
	space.controllers=this.options.system.refs.controllers;
	space.models=this.options.system.refs.models;
	space.functions=this.options.system.refs.functions;
}

/*****************************************************************************/
OneWorldCmsServer.prototype.configure=function(space,site) {
	this.views.setGlobalspace(space);
	this.views.setPaths(
		site.viewsconfig.views,
		site.viewsconfig.cache
//		[site.paths.views,this.options.system.paths.views],
//		[site.paths.cache,this.options.system.paths.cache]
	);
	if (!site.sql) {
		var arr=[site.paths.sql];
		if (site.preload) {
			for (var i=site.preload.length-1;i>=0;i--) arr.push(site.preload[i].paths.sql);
		}
		arr.push(this.options.system.paths.sql);
		site.sql=this.sql_module.connect(site.database,arr);
		site.mfact=new model_factory(site,space.functions.Model,Dumper);
		site.rewriter=new rewriter(site);
	}
	space.mfact=site.mfact;
	space.controllers=site.refs.controllers;
	space.models=site.refs.models;
	space.functions=site.refs.functions;
}

/*****************************************************************************/
OneWorldCmsServer.prototype.show_debug_page=function(space) {
	space.debug=Dumper({fields:space.fields,req:space.req,env:system.env,action:space.action});
	return this.views.process('system/debug_page',space);
}

/*****************************************************************************/
OneWorldCmsServer.prototype.render_http_error=function(space,errcode,descr) {
//	space.error_title=space.site_option(space,["errors",errcode,"title"]);
//	space.error=space.site_option(space,["errors",errcode,"body"]);
	if (errcode==403 && space.uid==0 && !space.fields.ajaj && space.site.auth && space.site.auth.prompt_login) {
		space.body=this.views.process("widgets/login",space);
		space.pageinfo={};
		return this.views.process("pagetemplates/login",space);
	}
	space.error_title=space.functions.L(space,"errors",errcode+"_title");
	space.error_descr=space.functions.L(space,"errors",errcode+"_descr");
	if (space.fields.ajaj) {
		return JSON.stringify({
			error_code:errcode,
			error_title:space.error_title,
			error:space.error_descr
		});
	}
	space.page.statusCode=errcode||500;
	space.error=descr;
	space.pageinfo={};
	space.body=this.views.process("errors/"+errcode,space);
	return this.views.process("pagetemplates/error",space);
}

/*****************************************************************************/
OneWorldCmsServer.prototype.mkpreview=function(space,filehead,type,typemo,fileext) {
	var size;
	var moval=50;
	var exact=0;
	var typemo1=typemo;
	var arr;
	if (arr=typemo.match(/^C(\d+)$/)) {
		moval=1*arr[1];
		typemo1="C";
		exact=1;
	}
	var basepath=space.site.paths.html;
	var previews=space.site.previews||this.options.system.previews;
	var xs=previews[type][0];
	var ys=previews[type][1];
	var f=new File(basepath+filehead+"."+fileext);
	if (!f.isFile()) {
		space.page.responseHeaders["Content-type"]="text/plain";
		space.page.statusCode=404;
		return "Ahem. no file "+filehead+"."+fileext+" found\n";
	}
	space.functions.scale_image(space,basepath+filehead+"."+fileext,basepath+filehead+"-preview"+type+typemo+"."+fileext,xs,ys,typemo1,moval,exact,fileext);
	var ret;
	try {
		var f=new File(basepath+filehead+"-preview"+type+typemo+"."+fileext);
		f.open("r");
		ret=f.read();
		f.close();
	} catch (e) {
		space.page.responseHeaders["Content-type"]="text/plain";
		space.page.statusCode=500;
		return "Error reading/writing file "+filehead+"-preview"+type+typemo+"."+fileext;
	}
	space.res.status(200);
	space.page.responseHeaders["Content-type"]=space.functions.guess_mime(space,fileext);
	space.res.header(space.page.responseHeaders);
	space.res.write(ret);
	space.page.no_output=1;
	return "";
}

OneWorldCmsServer.prototype.send_error_notification=send_error_notification;

/*****************************************************************************/
exports.createServer=function() {
	return new OneWorldCmsServer();
}

/*****************************************************************************/

